<!--
 * @Author: Dorange.Wang
 * @Date: 2021-04-09 16:10:26
 * @LastEditors: wangming
 * @LastEditTime: 2022-07-30 15:17:52
 * @Description: file content
-->
<template>
  <el-dialog
    v-if="showVisible"
    :visible="showVisible"
    center
    :show-close="false"
    width="600px"
  >
    <div class="b g3 f16 tl" slot="title">
      <div class="ks-row-between pl15 pr15">
        <span>{{ isNew ? "新建菜单" : "编辑菜单" }}</span>
        <span
          class="el-icon-close g9 f26 poi"
          @click="showVisible = false"
        ></span>
      </div>
    </div>

    <el-form class="pl30 pr30" :model="formData" ref="form" label-width="120px">
      <el-form-item
        label="菜单类型"
        prop="type"
        :rules="[
          { required: true, message: '请选择菜单类型', trigger: 'change' },
        ]"
      >
        <el-radio-group
          v-model="formData.type"
          :disabled="!isNew"
          @change="handleTypeChange"
        >
          <el-radio
            v-for="(value, key) in MENU_TYPE_ENUM"
            :key="key"
            :label="key"
            >{{ value }}
          </el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item
        label="菜单名称"
        prop="name"
        :rules="[
          { required: true, message: '菜单名称不能为空', trigger: 'change' },
        ]"
      >
        <el-input
          v-model="formData.name"
          style="width: 400px"
          placeholder="请输入菜单名称"
          :maxlength="64"
          show-word-limit
          :disabled="isBuildIn"
        />
      </el-form-item>

      <el-form-item prop="localism" label="菜单名称国际化" v-if="!isBuildIn">
        <GlobalizationConfigWord
          :localism="formData.localism"
          @setLangCode="setLangCode"
        />
      </el-form-item>
      <el-form-item label="菜单图标" prop="icon" v-if="!isBuildIn">
        <div class="menu-icon-box">
          <template v-if="formData.icon">
            <div class="menu-icon" v-if="appIcon" @click="handleIconSelect">
              <IconPark :type="formData.icon" />
            </div>

            <i
              v-else
              class="menu-icon"
              :class="formData.icon"
              @click="handleIconSelect"
            ></i>

            <el-button type="text" @click="handleIconClear">清空</el-button>
          </template>
          <el-button v-else type="text" @click="handleIconSelect"
            >选择icon
          </el-button>
        </div>
      </el-form-item>
      <template v-if="formData.type === 'SUB' && !isBuildIn">
        <el-form-item
          label="是否显示"
          prop="hidden"
          :rules="[
            {
              required: true,
              message: '请选择菜单是否显示',
              trigger: 'change',
            },
          ]"
        >
          <el-radio-group v-model="formData.hidden">
            <el-radio :label="0">是</el-radio>
            <el-radio :label="1">否</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item
          label="适用终端"
          prop="pageType"
          :rules="[
            { required: true, message: '请选择适用终端', trigger: 'change' },
          ]"
        >
          <el-radio-group
            v-model="formData.pageType"
            @change="handleDeviceChange"
          >
            <el-radio
              v-for="(value, key) in DEVICE_TYPE_ENUM"
              :key="key"
              :label="key"
              >{{ value }}
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <template v-if="appIcon">
          <el-form-item label="图标颜色">
            <div style="line-height: 1">
              <el-color-picker v-model="iconExtra.color"></el-color-picker>
            </div>
          </el-form-item>

          <el-form-item label="图标背景">
            <div style="line-height: 1">
              <el-color-picker v-model="iconExtra.background"></el-color-picker>
            </div>
          </el-form-item>
        </template>
        <el-form-item
          label="打开方式"
          prop="target"
          :rules="[
            { required: true, message: '请选择打开方式', trigger: 'change' },
          ]"
        >
          <el-radio-group
            v-model="formData.target"
            @change="$refs.form.clearValidate()"
          >
            <el-radio
              v-for="(value, key) in MENU_TARGET_ENUM"
              :key="key"
              :label="key"
              >{{ value }}
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item
          v-if="formData.target === 'OUTER'"
          label="带平台认证"
          prop="withToken"
          :rules="[
            {
              required: true,
              message: '请选择是否带平台认证',
              trigger: 'change',
            },
          ]"
        >
          <el-radio-group v-model="formData.withToken">
            <el-radio :label="1">是</el-radio>
            <el-radio :label="0">否</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item
          v-if="formData.target === 'OUTER'"
          label="菜单链接"
          prop="address"
          :rules="[
            { required: true, message: '请输入菜单链接', trigger: 'blur' },
            { pattern: URL_REG, message: '请输入有效地址', trigger: 'change' },
          ]"
        >
          <el-input
            v-model="formData.address"
            style="width: 400px"
            placeholder="请输入外部链接"
          />
        </el-form-item>
        <el-form-item
          ref="pageId"
          v-else
          label="菜单页面"
          prop="pageId"
          :rules="[
            { required: true, message: '请选择菜单页面', trigger: 'change' },
          ]"
        >
          <tree-select
            v-model="formData.pageId"
            :loading="pageLoading"
            style="width: 400px"
            placeholder="请选择"
            filterable
            :fieldMap="{
              value: 'id',
              label: 'name',
              disabled: 'disabled',
            }"
            :filterNodeMethod="filterNodeMethod"
            :treeData="pageList"
          />
        </el-form-item>
        <el-form-item
          label="上级目录"
          prop="parentId"
          :rules="[
            {
              required: true,
              message: '请选择上级目录',
              trigger: 'change',
            },
          ]"
        >
          <tree-select
            style="width: 400px"
            v-model="formData.parentId"
            :treeData="topMenu"
            @change="handleChangeTop"
          />
        </el-form-item>
      </template>
      <el-form-item
        label="排序"
        prop="serialNum"
        :rules="[
          { required: true, message: '排序不能为空', trigger: 'change' },
        ]"
      >
        <el-input-number
          v-model="formData.serialNum"
          :min="1"
          :max="999999999"
          style="width: 200px"
        ></el-input-number>
      </el-form-item>
    </el-form>

    <div slot="footer" class="tr">
      <el-button @click="showVisible = false">取 消</el-button>
      <el-button
        class="xxx"
        :loading="loading"
        :disabled="loading"
        type="primary"
        @click="submit"
        >确 定</el-button
      >
    </div>
  </el-dialog>
</template>

<script>
import GlobalizationConfigWord from "@/components/globalizationConfigWord.vue";
import lodash from "lodash";
import {
  MENU_TYPE_ENUM,
  DEVICE_TYPE_ENUM,
  MENU_TARGET_ENUM,
  PAGE_TYPE_ENUM,
} from "@/utils/enum";

import IconSelect from "@/components/IconSelect";
import BdIconSelect from "@/components/BdIconSelect";
import { postHmmenu, putHmmenu } from "@/apis/paas/HmMenuController.js";
import { getHmpagefolderListTree } from "@/apis/paas/HmPageFolderController.js";
import { filterNodeMethod } from "@/utils/treeSelectFormat";
import { IconPark } from "@icon-park/vue/es/all";
import { URL_REG } from "@/utils/reg";
const defaultFormData = {
  type: Object.keys(MENU_TYPE_ENUM)[0],
  target: Object.keys(MENU_TARGET_ENUM)[0],
  hidden: 0,
  pageType: Object.keys(DEVICE_TYPE_ENUM)[0],
  serialNum: 1,
  withToken: 1,
  localism: "",
};

const DEFAULT_ICON_EXTRA = {
  color: "#FFFFFF",
  background: "#1989FA",
};

function disabledTreeNodeCreate(tree) {
  return lodash.cloneDeep(tree).map((node) => {
    node.disabled = node.type === "SUB";
    node.children = disabledTreeNodeCreate(node.children);
    return node;
  });
}

function disabledTreeNodeEdit(tree, value) {
  return lodash.cloneDeep(tree).map((node) => {
    node.disabled =
      node._parentIds.includes(value) ||
      node.id === value ||
      node.type === "SUB";
    node.children = disabledTreeNodeEdit(node.children, value);
    return node;
  });
}

export default {
  name: "MenuForm",
  components: {
    IconPark,
    GlobalizationConfigWord,
  },
  props: {
    menuList: {
      // 记录已经生成的菜单页面
      type: Array,
      default: () => [],
    },
    treeData: {
      type: Array,
      default: () => [],
    },
  },

  data() {
    this.loadPageList = lodash.debounce(this.loadPageList, 500);
    return {
      loading: false,
      URL_REG,
      filterNodeMethod,
      DEVICE_TYPE_ENUM,
      MENU_TYPE_ENUM,
      MENU_TARGET_ENUM,
      showVisible: false,
      pageList: [],
      pageLoading: false,
      formData: {
        ...defaultFormData,
      },
      topMenu: [],
      iconExtra: { ...DEFAULT_ICON_EXTRA },
    };
  },

  watch: {
    showVisible(value) {
      if (value) {
        this.loading = false;
      }
    },
  },

  computed: {
    isNew() {
      return !this.formData.id;
    },
    appIcon() {
      const { type, pageType } = this.formData;
      return type === "SUB" && pageType === "APP";
    },
    isBuildIn() {
      return this.formData.pathName;
    },
  },

  created() {},

  methods: {
    setLangCode(props) {
      this.formData.localism = props;
    },
    showLabel(type) {
      const dec = PAGE_TYPE_ENUM[type];
      return `(${dec})`;
    },
    addForm(record = {}) {
      this.loadPageList();
      this.showVisible = true;
      this.formData = {
        ...defaultFormData,
        ...record,
      };
      this.iconExtra = { ...DEFAULT_ICON_EXTRA };
      this.topMenu = disabledTreeNodeCreate(this.treeData);
      this.getTopSerialNum();
      this.$nextTick(() => {
        this.$refs.form.clearValidate();
      });
    },

    editForm(record = {}) {
      this.loadPageList();
      this.formData = {
        localism: "",
        ...defaultFormData,
        ...record,
        serialNum: record.serialNum || defaultFormData.serialNum,
        pageType: record.pageType || "ALL",
        pageId: record.pageId ? ~~record.pageId : undefined,
      };
      try {
        this.iconExtra = JSON.parse(record.extra || "{}");
      } catch (err) {
        this.iconExtra = { ...DEFAULT_ICON_EXTRA };
      }
      this.topMenu = disabledTreeNodeEdit(this.treeData, record.id);
      this.localPageList();
      this.showVisible = true;
      this.$nextTick(() => {
        this.$refs.form.clearValidate();
      });
    },

    localPageList() {
      const { pageId, pageName } = this.formData;
      if (pageId) {
        this.pageList = [
          {
            id: pageId,
            name: pageName,
          },
        ];
      }
    },

    handleTypeChange() {
      this.$set(this.formData, "pageId", undefined);
      // 屏蔽多级目录，需要使用时移除 以下内容
      this.$set(this.formData, "parentId", undefined);
    },
    loadPageList() {
      this.pageLoading = true;
      getHmpagefolderListTree({ type: this.formData.pageType, excludeJson: true })
        .then((res) => {
          res.forEach((node) => {
            node.type = "folder";
          });
          this.pageList = this.createPageTreeNode(res);
        })
        .finally(() => {
          this.pageLoading = false;
        });
    },

    handleIconClear() {
      this.$set(this.formData, "icon", "");
    },

    handleIconSelect() {
      if (this.appIcon) {
        BdIconSelect.select(this.formData.icon).then((icon) => {
          this.$set(this.formData, "icon", icon);
        });
      } else {
        IconSelect.select(this.formData.icon).then((icon) => {
          this.$set(this.formData, "icon", icon);
        });
      }
    },
    async handleDeviceChange() {
      this.loadPageList();
      this.formData.pageId = "";
      this.formData.icon = "";
      await this.$nextTick();
      this.$refs.pageId.clearValidate();
    },
    getTopSerialNum() {
      const currentMax = Math.max.apply(
        Math,
        this.topMenu.map(function (o) {
          return o.pathName ? 0 : o.serialNum;
        })
      );
      this.$set(this.formData, "serialNum", currentMax + 1);
    },
    handleChangeTop(value) {
      const parent = this.topMenu.find((item) => item.id === value);
      if (parent?.children?.length) {
        const currentMax = Math.max.apply(
          Math,
          parent.children.map(function (o) {
            return o.serialNum;
          })
        );
        this.$set(this.formData, "serialNum", currentMax + 1);
      }
    },
    async submit() {
      this.loading = true;
      try {
        await this.$refs.form.validate();
        const {
          id,
          type,
          icon,
          name,
          pageId,
          parentId,
          serialNum,
          target,
          hidden,
          withToken,
          address,
          localism,
        } = this.formData;
        let params = {};
        let request = null;
        if (this.isNew) {
          params = {
            type,
            icon,
            name,
            pageId,
            parentId,
            serialNum,
            target,
            withToken,
            address,
            localism,
          };
          request = postHmmenu;
        } else {
          params = {
            id,
            icon,
            name,
            pageId,
            parentId,
            serialNum,
            target,
            withToken,
            address,
            localism,
          };
          request = putHmmenu;
        }
        if (type === "SUB") {
          params.hidden = hidden;
        }

        if (this.appIcon) {
          params.extra = JSON.stringify({
            color: this.iconExtra.color || DEFAULT_ICON_EXTRA.color,
            background:
              this.iconExtra.background || DEFAULT_ICON_EXTRA.background,
          });
        }

        for (const key in params) {
          params[key] =
            typeof params[key] === "string" ? params[key].trim() : params[key];
        }
        request(params).then((res) => {
          this.showVisible = false;

          this.$emit("ok");
        });
      } catch (error) {
        console.log(error);

        this.loading = false;
      }
    },
    createPageTreeNode(tree) {
      return lodash.cloneDeep(tree).map((node) => {
        node.disabled = node.type === "folder";
        if (node.pageResults) {
          node.id = "folder" + node.id;
          node.children = this.filterPageNoMenu(node.pageResults) || [];
          node.children.forEach((item) => {
            item.name = `${item.name}（${PAGE_TYPE_ENUM[item.type]}）`;
          });
        }
        return node;
      });
    },
    filterPageNoMenu(pageList) {
      const res = [];
      pageList.forEach((item) => {
        let flag = true;
        this.menuList.forEach((menu) => {
          if (menu.pageId === item.id && menu.pageId !== this.formData.pageId) {
            flag = false;
          }
        });
        if (flag) {
          res.push(item);
        }
      });
      return res;
    },
  },
};
</script>

<style lang="scss" scoped>
.menu-icon-box {
  display: flex;
  align-items: center;

  .menu-icon {
    font-size: 28px;
    margin-right: 20px;
    color: #1890ff;
    cursor: pointer;
  }
}
</style>
